﻿using System.Collections.Concurrent;
using System.Threading;
using Fetches.Fetch.Dto;
using Fetches.Fetch.Fetcher;
using Fetches.Fetch.Scheduler.Component;
using Fetches.Fetch.Utils;

namespace Fetches.Fetch.Scheduler
{
    public class QueueScheduler : AbstractScheduler
    {
        private ConcurrentQueue<Request> _queue = new ConcurrentQueue<Request>();
        private IDuplicateRemover _duplicateRemover;
        private readonly AtomicInteger _workingFetcher = new AtomicInteger();
        private readonly AtomicInteger _remainsCounter = new AtomicInteger();
        private readonly AtomicInteger _successCounter = new AtomicInteger();
        private readonly AtomicInteger _failureCounter = new AtomicInteger();
        private int _ready;

        public override void Initialize(string config, long uniqueId)
        {
            //这个设置只是我的想法,不是实测的合适数字
            var option = new BloomFilterOptions()
            {
                ExpectedInsertions = 1000000,
                FalsePositiveProbability = 0.01
            };
            _duplicateRemover = new BloomFilterDuplicateRemover(option);
        }

        public override Request Poll()
        {
            if (_queue.TryDequeue(out var request))
            {
                _remainsCounter.Decrement();
                return request;
            }

            return null;
        }

        protected override void PushWhenNoDuplicate(Request request)
        {
            _queue.Enqueue(request);
            _remainsCounter.Increment();
        }

        public override void Ack(Request request, bool success)
        {
            if (success)
            {
                _successCounter.Increment();
            }
            else
            {
                _failureCounter.Increment();
            }
        }

        public override bool IsFirstRun()
        {
            if (_ready > 0)
            {
                return false;
            }

            lock (_queue)
            {
                Interlocked.Increment(ref _ready);
                return _ready == 1;
            }
        }

        public override int WorkingFetcherCount()
        {
            return _workingFetcher.Value;
        }

        public override int RemainingRequestCount()
        {
            return _remainsCounter.Value;
        }

        public override FetchTaskProgress GetFetchProgress()
        {
            var progress = new FetchTaskProgress()
            {
                Remains = _remainsCounter.Value,
                Status = IsFetchFinished() ? FetchTaskStatus.Solved : FetchTaskStatus.Processing,
                Success = _successCounter.Value,
                Failure = _failureCounter.Value
            };
            return progress;
        }

        public override void FetcherStatusReport(AbstractFetcher fetcher)
        {
            if (fetcher.Status == FetcherStatus.Idle)
            {
                _workingFetcher.Decrement();
            }
            else
            {
                _workingFetcher.Increment();
            }
        }

        public override bool IsDuplicate(Request request)
        {
            return _duplicateRemover.IsDuplicate(request);
        }


        public override void ResetDuplicateCheck()
        {
            _duplicateRemover.ResetDuplicateCheck();
            _remainsCounter.Set(0);
        }

        public override void Dispose()
        {
            _duplicateRemover.Dispose();
        }
    }
}
